package com.swh.cloud.biz.ui.conf;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.CollectionUtils;

import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ConfigurationBasedServerList;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.PingUrl;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.netflix.loadbalancer.ServerListSubsetFilter;
import com.netflix.loadbalancer.WeightedResponseTimeRule;

/**
 * 配置ribbon的一些参数信息(包括负载均衡算法)
 * 在这里我们可以重写任何ribbon相关的一些bean,只需要把方法名写的和Spring Cloud Netflix提供的方法名一样就可以
 * @author sangwenhao-桑文豪
 * @date 2017年1月8日 下午8:23:50
 */
////@EnableConfigurationProperties
//@EnableAutoConfiguration
//@Configuration
//@PropertySource("classpath:config.properties")
public class BIZServerLBConfig /*extends RibbonClientConfiguration */{
    
   private static final Logger logger  = LoggerFactory.getLogger(BIZServerLBConfig.class);

  @Autowired
  IClientConfig config;
  
  @Value("${ribbon.client.name}")
  private String name ;
  /*
    @Bean
	public IClientConfig ribbonClientConfig() {
    	logger.info(">>>>>>>>>>>>初始化clientConfig:"+this.name);
		DefaultClientConfigImpl config = new DefaultClientConfigImpl();
		config.loadProperties(this.name);
		return config;
	}*/
  /*
  @Bean
  public IClientConfig config() {
//  	DefaultClientConfigImpl config = new DefaultClientConfigImpl();
//  	config.set(CommonClientConfigKey.ConnectTimeout, 1000);
//  	config.set(CommonClientConfigKey.ReadTimeout, 500) ;
  	
  	 IClientConfig config = IClientConfig.Builder.newBuilder("bizUI").
             withDefaultValues().
//             withDeploymentContextBasedVipAddresses("user-cloud-eureka-server").
             build().
             set(IClientConfigKey.Keys.MaxTotalConnections, 2000).
             set(IClientConfigKey.Keys.MaxConnectionsPerHost, 2000).
             set(IClientConfigKey.Keys.OkToRetryOnAllOperations, true).
             set(IClientConfigKey.Keys.NIWSServerListClassName, DiscoveryEnabledNIWSServerList.class.getName())
             .set(CommonClientConfigKey.ConnectTimeout, 3000)
             .set(CommonClientConfigKey.ReadTimeout, 3000)
             .set(CommonClientConfigKey.MaxAutoRetries, 1)
             .set(CommonClientConfigKey.MaxAutoRetriesNextServer, 1)
//             .set(CommonClientConfigKey.NFLoadBalancerRuleClassName, WeightedResponseTimeRule.class.getName())
             ;
  	logger.info(">>>>>>>>>>>>初始化clientConfig:"+ReflectionToStringBuilder.toString(config));
  	return config;
  }
  */
  /**
   * 重写IPing,嗅探服务是否可用，默认是OpPing(不进行嗅探,始终返回true) 
   * @param config
   * @return
   * @author sangwenhao-桑文豪
   * @date 2017年1月8日 下午9:06:02
   */
  @Bean
  public IPing ribbonPing(IClientConfig config) {
    logger.info(">>>>>>>>>>>>进入ribbonPing ");
    return new PingUrl();//返回200 认为服务可用
  }
  
  /**
   * 重写IRule规则,负责均衡的规则
   * @param config
   * @return
   * @author sangwenhao-桑文豪
   * @date 2017年1月8日 下午9:06:13
   */
  @Bean
  public IRule ribbonRule(IClientConfig config) {
      logger.info(">>>>>>>>>>>>进入ribbonRule name:"+this.name);
//	  return new ZoneAvoidanceRule();//springCloud封装后默认的负载规则，复合判断server所在区域的性能和server的可用性选择server
//	  return new BestAvailableRule();//并发请求数最小
//    return new AvailabilityFilteringRule();//该策略通过线性抽样的方式直接尝试寻找可用且较空闲的实例来使用，优化了父类每次都要遍历所有实例的开销
    return new WeightedResponseTimeRule();//响应时间权重算法，最终根据权重区间选择，服务的响应时间越短，区间越大，被选中的概率就越大
  }
  
  /**
   *  获取服务列表的方法
   * @param config
   * @return
   * @author sangwenhao-桑文豪
   * @date 2017年1月8日 下午9:06:24
   */
  @Bean
  public ServerList<Server> ribbonServerList(IClientConfig config) {
      logger.info(">>>>>>>>>>>>进入ribbonServerList ");
      BazServiceList serverList = new BIZServerLBConfig.BazServiceList(config);
      List<Server> serverDetailList = serverList.getInitialListOfServers();
      if (!CollectionUtils.isEmpty(serverDetailList)) {
          for (Server s : serverDetailList) {
              logger.info(">>>>>>>>>>>>获取服务信息 "+s.getHost() + ":" + s.getPort());
          }
      } else {
	  logger.info(">>>>>>>>>>>>获取服务信息 no service");
      }
      return serverList ;
  }

  /**
   * 
   * @return
   * @author sangwenhao-桑文豪
   * @date 2017年1月8日 下午9:09:06
   */
  @Bean
  public ServerListSubsetFilter serverListFilter() {
      logger.info(">>>>>>>>>>>>进入serverListFilter ");
      ServerListSubsetFilter filter = new ServerListSubsetFilter();
      return filter;
  }
  
  /**
   * 可自定义获取服务列表的方法
   * @author sangwenhao-桑文豪
   * @date 2017年1月8日 下午9:08:37
   */
  public static class BazServiceList extends ConfigurationBasedServerList {
      public BazServiceList(IClientConfig config) {
	  logger.info(">>>>>>>>>>>>进入BazServiceList ");
          super.initWithNiwsConfig(config);
      }
  }

public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}

}
